"""Settings Interface - Global Configuration Management.

This module provides the graphical user interface for managing global application settings.
"""

from pathlib import Path

from PySide6.QtCore import Signal
from PySide6.QtWidgets import (
    QCheckBox,
    QComboBox,
    QDialog,
    QFileDialog,
    QFormLayout,
    QGroupBox,
    QHBoxLayout,
    QLineEdit,
    QPushButton,
    QSpinBox,
    QTabWidget,
    QVBoxLayout,
    QWidget,
)

from ..models.database import db
from ..models.task import GlobalConfig


class SettingsDialog(QDialog):
    """Dialog for managing global application settings.

    This dialog allows users to configure various aspects of the application,
    such as download behavior, network settings, automation, and UI preferences.
    """

    settings_saved = Signal()

    def __init__(self, parent: QWidget | None = None):
        """Initializes the settings dialog.

        Args:
            parent: The parent widget, defaults to None.
        """
        super().__init__(parent)
        self.config: GlobalConfig | None = None
        self.setWindowTitle("设置")
        self.setMinimumSize(600, 500)
        self.init_ui()
        self.load_config()

    def init_ui(self) -> None:
        """Initializes the user interface components of the settings dialog,
        including tab widgets for different setting categories and action buttons.
        """
        layout = QVBoxLayout()

        # 标签页
        tab_widget = QTabWidget()
        tab_widget.addTab(self.create_download_tab(), "下载设置")
        tab_widget.addTab(self.create_network_tab(), "网络设置")
        tab_widget.addTab(self.create_automation_tab(), "自动化")
        tab_widget.addTab(self.create_ui_tab(), "界面")

        layout.addWidget(tab_widget)

        # 按钮
        button_layout = QHBoxLayout()
        button_layout.addStretch()

        save_btn = QPushButton("保存")
        save_btn.clicked.connect(self.save_settings)
        button_layout.addWidget(save_btn)

        cancel_btn = QPushButton("取消")
        cancel_btn.clicked.connect(self.reject)
        button_layout.addWidget(cancel_btn)

        layout.addLayout(button_layout)
        self.setLayout(layout)

    def create_download_tab(self) -> QWidget:
        """Creates the download settings tab, allowing configuration of concurrent downloads, save paths, and speed limits."""
        widget = QWidget()
        layout = QVBoxLayout()

        # 基本设置组
        basic_group = QGroupBox("基本设置")
        basic_layout = QFormLayout()

        self.concurrent_spin = QSpinBox()
        self.concurrent_spin.setRange(1, 10)
        self.concurrent_spin.setValue(3)
        basic_layout.addRow("最大并发下载数:", self.concurrent_spin)

        self.save_path_edit = QLineEdit()
        self.save_path_edit.setText(str(Path.home() / "Downloads"))
        browse_btn = QPushButton("浏览...")
        browse_btn.clicked.connect(self.browse_save_path)
        path_layout = QHBoxLayout()
        path_layout.addWidget(self.save_path_edit)
        path_layout.addWidget(browse_btn)
        basic_layout.addRow("默认保存路径:", path_layout)

        self.threads_spin = QSpinBox()
        self.threads_spin.setRange(1, 16)
        self.threads_spin.setValue(4)
        basic_layout.addRow("默认并行线程数:", self.threads_spin)

        self.auto_resume_check = QCheckBox("启用自动断点续传")
        self.auto_resume_check.setChecked(True)
        basic_layout.addRow(self.auto_resume_check)

        basic_group.setLayout(basic_layout)
        layout.addWidget(basic_group)

        # 速度限制组
        speed_group = QGroupBox("速度限制")
        speed_layout = QFormLayout()

        self.speed_limit_spin = QSpinBox()
        self.speed_limit_spin.setRange(0, 10000)
        self.speed_limit_spin.setSuffix(" MB/s")
        self.speed_limit_spin.setSpecialValueText("无限制")
        speed_layout.addRow("全局下载限速:", self.speed_limit_spin)

        self.idle_mode_check = QCheckBox("启用闲时下载模式")
        speed_layout.addRow(self.idle_mode_check)

        self.idle_threshold_spin = QSpinBox()
        self.idle_threshold_spin.setRange(1, 60)
        self.idle_threshold_spin.setValue(10)
        self.idle_threshold_spin.setSuffix(" 分钟")
        speed_layout.addRow("闲置阈值:", self.idle_threshold_spin)

        speed_group.setLayout(speed_layout)
        layout.addWidget(speed_group)

        layout.addStretch()
        widget.setLayout(layout)
        return widget

    def create_network_tab(self) -> QWidget:
        """Creates the network settings tab, including options for proxy configuration and connection timeouts."""
        widget = QWidget()
        layout = QVBoxLayout()

        # 代理设置组
        proxy_group = QGroupBox("代理设置")
        proxy_layout = QFormLayout()

        self.proxy_edit = QLineEdit()
        self.proxy_edit.setPlaceholderText("例如: http://127.0.0.1:7890")
        proxy_layout.addRow("默认代理:", self.proxy_edit)

        self.timeout_spin = QSpinBox()
        self.timeout_spin.setRange(5, 300)
        self.timeout_spin.setValue(30)
        self.timeout_spin.setSuffix(" 秒")
        proxy_layout.addRow("连接超时:", self.timeout_spin)

        proxy_group.setLayout(proxy_layout)
        layout.addWidget(proxy_group)

        layout.addStretch()
        widget.setLayout(layout)
        return widget

    def create_automation_tab(self) -> QWidget:
        """Creates the automation settings tab, providing options for automatic download starts, post-processing, and shutdown after completion."""
        widget = QWidget()
        layout = QVBoxLayout()

        # 自动化设置组
        auto_group = QGroupBox("自动化操作")
        auto_layout = QFormLayout()

        self.auto_start_check = QCheckBox("自动开始下载")
        self.auto_start_check.setChecked(True)
        auto_layout.addRow(self.auto_start_check)

        self.post_process_check = QCheckBox("启用下载后处理")
        self.post_process_check.setChecked(True)
        auto_layout.addRow(self.post_process_check)

        self.shutdown_check = QCheckBox("完成后关机")
        auto_layout.addRow(self.shutdown_check)

        auto_group.setLayout(auto_layout)
        layout.addWidget(auto_group)

        layout.addStretch()
        widget.setLayout(layout)
        return widget

    def create_ui_tab(self) -> QWidget:
        """Creates the UI settings tab, allowing configuration of language, theme, and system tray behavior."""
        widget = QWidget()
        layout = QVBoxLayout()

        # 界面设置组
        ui_group = QGroupBox("界面设置")
        ui_layout = QFormLayout()

        self.language_combo = QComboBox()
        self.language_combo.addItems(["简体中文", "English"])
        ui_layout.addRow("语言:", self.language_combo)

        self.theme_combo = QComboBox()
        self.theme_combo.addItems(["自动", "浅色", "深色"])
        ui_layout.addRow("主题:", self.theme_combo)

        self.tray_check = QCheckBox("启用系统托盘")
        self.tray_check.setChecked(True)
        ui_layout.addRow(self.tray_check)

        self.minimize_tray_check = QCheckBox("最小化到托盘")
        self.minimize_tray_check.setChecked(True)
        ui_layout.addRow(self.minimize_tray_check)

        ui_group.setLayout(ui_layout)
        layout.addWidget(ui_group)

        # 隐私设置组
        privacy_group = QGroupBox("隐私设置")
        privacy_layout = QFormLayout()

        self.encrypt_cookies_check = QCheckBox("加密Cookie存储")
        self.encrypt_cookies_check.setChecked(True)
        privacy_layout.addRow(self.encrypt_cookies_check)

        self.clear_history_check = QCheckBox("退出时清除历史")
        privacy_layout.addRow(self.clear_history_check)

        privacy_group.setLayout(privacy_layout)
        layout.addWidget(privacy_group)

        layout.addStretch()
        widget.setLayout(layout)
        return widget

    def browse_save_path(self, line_edit: QLineEdit) -> None:
        """Opens a file dialog to select a save path and updates the given QLineEdit.

        Args:
            line_edit: The QLineEdit widget to update with the selected path.
        """
        directory = QFileDialog.getExistingDirectory(self, "选择保存路径")

    def load_config(self) -> None:
        """Loads the global configuration from the database into the UI fields of the settings dialog."""
        import asyncio

        async def _load():
            await db.initialize()
            async with db.session() as session:
                from sqlalchemy import select

                result = await session.execute(select(GlobalConfig).where(GlobalConfig.id == 1))
                self.config = result.scalar_one_or_none()

                if self.config:
                    # 应用配置到UI
                    self.concurrent_spin.setValue(self.config.max_concurrent_downloads)
                    self.save_path_edit.setText(self.config.default_save_path)
                    self.threads_spin.setValue(self.config.default_threads)
                    self.auto_resume_check.setChecked(bool(self.config.enable_auto_resume))
                    self.auto_start_check.setChecked(bool(self.config.auto_start_downloads))
                    self.post_process_check.setChecked(bool(self.config.enable_post_processing))
                    self.shutdown_check.setChecked(bool(self.config.shutdown_after_completion))
                    self.idle_mode_check.setChecked(bool(self.config.enable_idle_mode))
                    self.idle_threshold_spin.setValue(self.config.idle_threshold_minutes)
                    self.timeout_spin.setValue(self.config.timeout)

                    if self.config.default_proxy:
                        self.proxy_edit.setText(self.config.default_proxy)

                    if self.config.global_speed_limit:
                        self.speed_limit_spin.setValue(self.config.global_speed_limit // (1024 ** 2))

                    self.tray_check.setChecked(bool(self.config.enable_system_tray))
                    self.minimize_tray_check.setChecked(bool(self.config.minimize_to_tray))
                    self.encrypt_cookies_check.setChecked(bool(self.config.encrypt_cookies))
                    self.clear_history_check.setChecked(bool(self.config.clear_history_on_exit))

        # 在新的事件循环中运行
        loop = asyncio.new_event_loop()
        asyncio.set_event_loop(loop)
        loop.run_until_complete(_load())

    def save_settings(self) -> None:
        """Saves the current UI settings from the settings dialog to the global configuration in the database."""
        import asyncio

        async def _save():
            async with db.session() as session:
                if self.config:
                    # 更新配置
                    self.config.max_concurrent_downloads = self.concurrent_spin.value()
                    self.config.default_save_path = self.save_path_edit.text()
                    self.config.default_threads = self.threads_spin.value()
                    self.config.enable_auto_resume = int(self.auto_resume_check.isChecked())
                    self.config.auto_start_downloads = int(self.auto_start_check.isChecked())
                    self.config.enable_post_processing = int(self.post_process_check.isChecked())
                    self.config.shutdown_after_completion = int(self.shutdown_check.isChecked())
                    self.config.enable_idle_mode = int(self.idle_mode_check.isChecked())
                    self.config.idle_threshold_minutes = self.idle_threshold_spin.value()
                    self.config.timeout = self.timeout_spin.value()
                    self.config.default_proxy = self.proxy_edit.text() or None

                    speed_limit = self.speed_limit_spin.value()
                    self.config.global_speed_limit = (
                        speed_limit * 1024 ** 2 if speed_limit > 0 else None
                    )

                    self.config.enable_system_tray = int(self.tray_check.isChecked())
                    self.config.minimize_to_tray = int(self.minimize_tray_check.isChecked())
                    self.config.encrypt_cookies = int(self.encrypt_cookies_check.isChecked())
                    self.config.clear_history_on_exit = int(self.clear_history_check.isChecked())

                    session.add(self.config)
                    await session.commit()

        loop = asyncio.new_event_loop()
        asyncio.set_event_loop(loop)
        loop.run_until_complete(_save())

        self.settings_saved.emit()
        self.accept()
